/*
 * @Author: c
 * @Date: 2024-01-22 03:26:24
 * @LastEditTime: 2024-02-26 22:15:46
 * @LastEditors: c
 * @Description:
 * @FilePath: \music-web-admin\src\utils\ffmpeg\ffmpeg.ts
 * https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
// Copyright 2024 Administrator
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { AudioRateEnum } from "@/enums/audio.enum";
import { FFmpeg } from "@ffmpeg/ffmpeg";
import type { LogEvent } from "@ffmpeg/ffmpeg/dist/esm/types";
import { fetchFile, toBlobURL } from "@ffmpeg/util";
import { FormatType, MimeEnum, ProgressFuc } from "./type";

export class FFmpegClass {
  private static ffmpeg: FFmpeg;

  static getInstance() {
    if (!this.ffmpeg) {
      this.ffmpeg = new FFmpeg();
    }
    return this.ffmpeg;
  }

  /**
   * 压缩音频
   */
  static async operateAudioFile(
    file: File,
    outFormat: FormatType,
    ab: AudioRateEnum = AudioRateEnum.LOSSY,
    progressfc: ProgressFuc,
    isCut: boolean = false,
    time: number = 30
  ): Promise<Blob> {
    const baseURL =
      import.meta.env.VITE_FFMPEG_BASE_URL ||
      "https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm";

    const ffmpeg = new FFmpeg();
    // const ffmpeg = this.getInstance();

    ffmpeg.on("log", ({ message: msg }: LogEvent) => {
      // console.log(msg);
    });

    ffmpeg.on(
      "progress",
      ({ progress, time }: { progress: number; time: number }) => {
        console.log(
          `${progress * 100} % (transcoded time: ${time / 1000000} s)`
        );
        progressfc(progress * 100, time / 1000000);
      }
    );

    await ffmpeg.load({
      coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
      wasmURL: await toBlobURL(
        `${baseURL}/ffmpeg-core.wasm`,
        "application/wasm"
      ),
      workerURL: await toBlobURL(
        `${baseURL}/ffmpeg-core.worker.js`,
        "text/javascript"
      ),
    });
    // const fileUrl = URL.createObjectURL(file);

    await ffmpeg.writeFile(
      file.name,
      await fetchFile(
        file
        // "http://127.0.0.1:9000/public/%E6%AF%9B%E4%B8%8D%E6%98%93%20-%20%E5%80%9F.flac"
      )
    );
    let args = [
      "-i",
      file.name,
      "-ab", //音频比特率是指单位时间内音频所占用的比特大小，比特率越大音质越好，但相应地体积也越大。eg(32k 64k 128k)
      `${ab}k`,
    ];

    let opt = [`out.${outFormat}`];

    let cutargs = ["-ss", "0:0:0", "-t", `0:0:${time}`];
    if (isCut) {
      args = args.concat(cutargs);
    }

    args = args.concat(opt);

    await ffmpeg.exec(args);
    const data = await ffmpeg.readFile(`out.${outFormat}`);
    // const url = URL.createObjectURL(
    //   new Blob([(data as Uint8Array).buffer], { type: MimeEnum[outFormat] })
    // );

    ffmpeg.terminate();

    return new Blob([(data as Uint8Array).buffer], {
      type: MimeEnum[outFormat],
    });
  }
}

export function fileToBase64(
  file: File,
  cb: Function
): Promise<{ url: any; filename: string }> {
  const fileReader = new FileReader();
  fileReader.readAsDataURL(file);
  var filename = file.name;
  fileReader.addEventListener("progress", (e: ProgressEvent<FileReader>) => {
    cb(e);
  });

  return new Promise((resolve, reject) => {
    fileReader.addEventListener(
      "loadend",
      (e: ProgressEvent<FileReader>) => {
        var url: any = e.target!.result;

        resolve({ url, filename });
      },
      false
    );
  });
}

export function fileToArrayBuffer(
  file: File
): Promise<{ buf: any; filename: string }> {
  const fileReader = new FileReader();
  fileReader.readAsArrayBuffer(file);
  var filename = file.name;
  return new Promise((resolve, reject) => {
    fileReader.addEventListener(
      "loadend",
      (e: ProgressEvent<FileReader>) => {
        var buf: any = e.target!.result;
        resolve({ buf, filename });
      },
      false
    );
  });
}

// 获取视频当前帧图像信息与饱和度
export function getVideoPosterInfo(
  url: string
): Promise<{ imageData: Blob | null }> {
  return new Promise((resolve, reject) => {
    const video = document.createElement("video");
    video.setAttribute("crossOrigin", "Anonymous"); // 处理跨域
    video.setAttribute("src", url);
    // 可以设置创建视频有固定的宽高
    video.setAttribute("width", "640");
    video.setAttribute("height", "360");
    video.setAttribute("preload", "auto"); // auto|metadata|none

    // 监听：异常
    video.addEventListener("error", (error) => {
      reject(error);
    });
    // video.currentTime = 3
    video.addEventListener("canplay", () => {
      const canvas = document.createElement("canvas");
      const { width, height } = video;
      canvas.width = width || 640;
      canvas.height = height || 360;
      const ctx = canvas.getContext("2d");
      // 将视频对象直接绘入canvas
      ctx!.drawImage(video, 0, 0, width, height);
      canvas.toBlob((blob) => {
        resolve({ imageData: blob });
      });
    });
  });
}
